/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server;

/**
 *
 * @author pc0129
 */
import java.net.*;
import java.io.*;
import java.math.*;
import java.util.*;

public class KKMultiServer {

    static ArrayList<String> factors = new ArrayList<String>();
    static BigInteger target = null;
    static BigInteger currentLowerBound = new BigInteger("2");
    static BigInteger upperBound = null;
    static int numThreads = 0;
    static int numReturns = 0;
    static long startDate;
    static long endDate;
    static String filename = new String();

    public static void main(String[] args) throws IOException {
        filename = args[1];
        startDate = new Date().getTime();
        KKMultiServer k = new KKMultiServer();
        ServerSocket serverSocket = null;
        boolean listening = true;
        target = new BigInteger(args[0]);
        upperBound = k.sqrt(target);
        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 4444.");
            System.exit(-1);
        }

        while (listening) {
            new KKMultiServerThread(serverSocket.accept()).start();
        }
        serverSocket.close();
    }

    public synchronized static String getNewTask() {
        /*if ((currentLowerBound.compareTo(upperBound.add(new BigInteger("240000")))) == 1 && (target.compareTo(new BigInteger ("100000")) ==1)) {
        BigInteger test = new BigInteger("1");
        for (String s : factors) {
        test = new BigInteger(s).multiply(test);
        }
        factors.add(target.divide(test).toString());
        test = new BigInteger(factors.get(factors.size() - 1)).multiply(test);
        System.out.println(test.toString());
        System.out.println(factors);
        endDate = new Date().getTime();
        System.out.println("task took:" + (endDate - startDate) / 1000 + "seconds");
        System.exit(0);
        //return "STOP";
        }*/
        BigInteger test = new BigInteger("1");
        for (String s : factors) {
            test = new BigInteger(s).multiply(test);
        }
        if (test.compareTo(target) == 0) {
            System.out.println(writeFile(filename, factors));
            System.out.println(factors);
            System.out.println(test.toString());
            endDate = new Date().getTime();
            System.out.println("task took:" + (endDate - startDate) / 1000 + "seconds");
            System.exit(0);
        }
        //System.out.println(currentLowerBound.toString());
        String lowerBound = currentLowerBound.toString();
        String upperLimit = currentLowerBound.add(new BigInteger("120000")).toString();
        String search = target.toString();
        String command = new String(search + " " + lowerBound + " " + upperLimit);
        currentLowerBound = currentLowerBound.add(new BigInteger("120000"));
        return command;
    }

    public static boolean writeFile(String filename, ArrayList<String> array) {
        File writeFile = new File(filename);
        boolean status = true;
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(writeFile));
            for (String i : array) {
                writer.write(i);
                writer.newLine();
            }
            writer.close();
        } catch (IOException e) {
            System.err.println(e.getMessage());
            status = false;
            System.exit(0);

        }
        return status;
    }

    public BigInteger sqrt(BigInteger input) {
        int length = input.toString().length();
        //double estimate = 0;
        BigInteger firstterm = new BigInteger("10");
        if (length % 2 == 0) {
            //estimate = 7 * Math.pow(10, (length / 2) - 1);
            firstterm = firstterm.pow((length / 2) - 1).multiply(new BigInteger("7"));
        }

        if (length % 2 == 1) {
            //estimate = 2 * Math.pow(10, (length-1)/2);
            firstterm = firstterm.pow((length - 1) / 2).multiply(new BigInteger("2"));
        }

        BigInteger BigEstimate = new BigInteger(firstterm.toString());

        for (int k = 0; k <
                6; k++) {
            BigEstimate = (BigEstimate.add(input.divide(BigEstimate))).divide(new BigInteger("2"));
        }

        return BigEstimate;
    }
}
